#include "project.h"

#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QRegExp>
#include <QTextStream>
#include <QtDebug>


Project::Project(const QString& sourcePath)
{
    m_path  = sourcePath;
    m_valid = false;

    if(!sourcePath.isEmpty() && sourcePath.endsWith(".dat", Qt::CaseInsensitive))
    {
        this->loadData(sourcePath);
        this->loadDescriptor(sourcePath);
    }
}

void Project::update()
{
    loadData(sourcePath());
}

void Project::update(const QString &columnName, int operation, double value)
{
    if(m_xdata.contains(columnName))
    {
        QVector<double>& xdata = m_xdata[columnName];
        switch(operation)
        {
        case Plus:
            if(!xdata.isEmpty())
            {
                for(int i=0; i<xdata.size(); i++)
                {
                    xdata[i] += value;
                }
            }
            break;
    
        case Minus:
            if(!xdata.isEmpty())
            {
                for(int i=0; i<xdata.size(); i++)
                {
                    xdata[i] -= value;
                }
            }
            break;
    
        case Multiply:
            if(!xdata.isEmpty() && value != 0)
            {
                for(int i=0; i<xdata.size(); i++)
                {
                    xdata[i] *= value;
                }
            }
            break;

        case Devide:
            if(!xdata.isEmpty() && value != 0)
            {
                for(int i=0; i<xdata.size(); i++)
                {
                    xdata[i] /= value;
                }
            }
            break;

        default:
            break;
        }
    }

    if(m_ydata.contains(columnName))
    {
        QVector<double>& ydata = m_ydata[columnName];
        switch(operation)
        {
        case Plus:
            if(!ydata.isEmpty())
            {
                for(int i=0; i<ydata.size(); i++)
                {
                    ydata[i] += value;
                }
            }
            break;

        case Minus:
            if(!ydata.isEmpty())
            {
                for(int i=0; i<ydata.size(); i++)
                {
                    ydata[i] -= value;
                }
            }
            break;

        case Multiply:
            if(!ydata.isEmpty() && value != 0)
            {
                for(int i=0; i<ydata.size(); i++)
                {
                    ydata[i] *= value;
                }
            }
            break;

        case Devide:
            if(!ydata.isEmpty() && value != 0)
            {
                for(int i=0; i<ydata.size(); i++)
                {
                    ydata[i] /= value;
                }
            }
            break;

        default:
            break;
        }
    }
}

void Project::loadData(const QString& sourcePath)
{
    QFile source(sourcePath);
    if(!source.open(QFile::ReadOnly | QFile::Text))
    {
        return;
    }

    QList<QVector<double> > data;

    QTextStream in(&source);
    if(!in.atEnd())
    {
        QString line = in.readLine(1024).replace('\t', " ", Qt::CaseInsensitive).trimmed();
        QTextStream inx(&line);

        while(!inx.atEnd())
        {
            double value;
            QVector<double> columnData;
            inx >> value;
            columnData << value;
            data << columnData;
        }
    }
    while(!in.atEnd())
    {
        QString line = in.readLine(1024).replace('\t', " ", Qt::CaseInsensitive).trimmed();
        QTextStream inx(&line);

        if(!inx.atEnd())
        {
            for(int i=0; i<data.size(); i++)
            {
                double value;
                inx >> value;
                data[i] << value;
            }
        }
    }

    source.close();

    for(int i=0; i<data.size(); i++)
    {
        m_xdata[tr("Column %1").arg(QString::number(i+1))] = data[i];
        m_ydata[tr("Column %1").arg(QString::number(i+1))] = data[i];
    }

    m_valid = true;
}

void Project::loadDescriptor(const QString &sourcePath)
{
    QString descriptorPath = sourcePath + ".sqr";
    if(!QFileInfo(descriptorPath).exists())
    {
        descriptorPath = QFileInfo(sourcePath).dir().absoluteFilePath("global.sqr");
        if(!QFileInfo(descriptorPath).exists())
        {
            descriptorPath = QString();
        }
    }

    QFile descriptor(descriptorPath);
    if(!descriptor.open(QFile::ReadOnly | QFile::Text))
    {
        return;
    }

    QString text = QTextStream(&descriptor).readAll().trimmed();

    descriptor.close();

    if(text.isEmpty() || !text.startsWith("#!Squirrel", Qt::CaseSensitive))
    {
        return;
    }

    QMap<QString, QVector<double> > xdata = m_xdata;
    QMap<QString, QVector<double> > ydata = m_ydata;

    m_xdata.clear();
    m_ydata.clear();

    QTextStream ina(&text);

    while(!ina.atEnd())
    {
        QString line = ina.readLine().trimmed();

        if(line.contains(QRegExp("^[xy]", Qt::CaseInsensitive)))
        {
            QStringList words = line.split("=", QString::SkipEmptyParts);

            if(words.length() == 2)
            {
                QString rawIndex = words[1].trimmed();

                QTextStream inc(&rawIndex);

                while(!inc.atEnd())
                {
                    int index;

                    inc >> index;

                    QString columnName = tr("Column %1").arg(QString::number(index));

                    if("x" == words[0].trimmed().toLower())
                    {
                        if(xdata.contains(columnName))
                        {
                            m_xdata[columnName] = xdata[columnName];
                        }
                    }
                    else
                    {
                        if(ydata.contains(columnName))
                        {
                            m_ydata[columnName] = ydata[columnName];
                        }
                    }
                }
            }
        }
    }

    QTextStream inb(&text);

    while(!inb.atEnd())
    {
        QString line = inb.readLine().trimmed();

        if(line.contains(QRegExp("^[0-9]{1,3}", Qt::CaseInsensitive)))
        {
            QStringList words = line.split("=", QString::SkipEmptyParts);

            if(words.length() == 2)
            {
                bool ok;

                int index = words[0].trimmed().toInt(&ok);

                if(ok)
                {
                    QString columnName = tr("Column %1").arg(QString::number(index));

                    if(m_xdata.contains(columnName))
                    {
                        m_xdata[words[1].trimmed()] = m_xdata.take(columnName);
                    }
                    if(m_ydata.contains(columnName))
                    {
                        m_ydata[words[1].trimmed()] = m_ydata.take(columnName);
                    }
                }
            }
        }
    }
}
